package org.stvd.service.oauth;

import java.sql.Types;

import javax.sql.DataSource;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.SqlLobValue;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.stvd.common.Consts;

/**
 * 扩展默认的 TokenStore, 增加对缓存的支持
 */
public class CustomJdbcTokenStore extends JdbcTokenStore {


    private static final String insertOauthAccessTokenSql = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)";
    private static final String updateOauthAccessTokenSql = "update oauth_access_token set token=?, authentication_id=?, user_name=?, client_id=?, authentication=?, refresh_token=? where token_id=?";

    private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
    private final JdbcTemplate jdbcTemplate;
    
    public CustomJdbcTokenStore(DataSource dataSource) {
        super(dataSource);
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        
    }


    public OAuth2AccessToken readAccessToken(String tokenValue) {
        return super.readAccessToken(tokenValue);
    }


    public void removeAccessToken(String tokenValue) {
        super.removeAccessToken(tokenValue);
    }

    public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
        String refreshToken = null;
        if (token.getRefreshToken() != null) {
            refreshToken = token.getRefreshToken().getValue();
        }
        
        if (readAccessToken(token.getValue())!=null) {
//            removeAccessToken(token.getValue());
            jdbcTemplate.update(updateOauthAccessTokenSql, new Object[] { 
                    new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication),
                    authentication.isClientOnly() ? null : authentication.getName(),
                    authentication.getOAuth2Request().getClientId(),
                    new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken),
                    extractTokenKey(token.getValue())}, new int[] {
                    Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR});
        } else {
            jdbcTemplate.update(insertOauthAccessTokenSql, new Object[] { extractTokenKey(token.getValue()),
                    new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication),
                    authentication.isClientOnly() ? null : authentication.getName(),
                    authentication.getOAuth2Request().getClientId(),
                    new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] {
                    Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR });
        }
    }
    
    public OAuth2RefreshToken readRefreshToken(String token) {
        return super.readRefreshToken(token);
    }

    public void removeRefreshToken(String token) {
        super.removeRefreshToken(token);
    }


}
